﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Simulator
{
	public partial class ComboBoxVLAN : ComboBox
	{
		bool _canSelectAll;
		const int NumberOfItems = 8;
		const string AllVlansText = "(all VLANs)";
		int _selectedVlan;

		public ComboBoxVLAN ()
		{
			InitializeComponent ();

			_canSelectAll = false;
			_selectedVlan = -1;

			for (int i = 1; i <= NumberOfItems; i++)
				base.Items.Add (i.ToString ());			
		}

		[Browsable (false)]
		public bool IsDesignerHosted
		{
			get
			{
				Control ctrl = this;

				while (ctrl != null)
				{
					if ((ctrl.Site != null) && ctrl.Site.DesignMode)
						return true;
					ctrl = ctrl.Parent;
				}
				return false;
			}
		}

		[DefaultValue (false)]
		public bool CanSelectAllVLANs
		{
			get { return _canSelectAll; }
			set
			{
				if (_canSelectAll == value)
					return;

				_canSelectAll = value;

				if (_canSelectAll)
				{
					// Before: We couldn't select all (there was no "(all VLANs)" item),
					// Now:    We can select all (we must insert the "(all VLANs)" item).

					Items.Insert (0, AllVlansText);
					SelectedIndex = 0;
					_selectedVlan = -1;
					OnVlanChanged (EventArgs.Empty);
				}
				else
				{
					// Before: We could select all (there was an "(all VLANs)" item),
					// Now:    We can't select all (we must remove that item, if it exists).

					throw new NotImplementedException ();
					/*
					if (Items.Count > 0)
					{
						Debug.Assert (Items [0] as string == AllVlansText);
						Items.RemoveAt (0);

						Debug.Assert (Items.Count > 0);
						SelectedIndex = 0; // VLAN 1
						_selectedVlan = 1;
					}
					*/
				}
			}
		}

		public event EventHandler<EventArgs> VlanChanged;

		protected virtual void OnVlanChanged (EventArgs e)
		{
			if (VlanChanged != null)
				VlanChanged (this, e);
		}

		public int SelectedVlanNumber
		{
			get { return _selectedVlan; }
		}

		public void SelectVlan (int vlanNumber)
		{
			if ((vlanNumber != -1) && ((vlanNumber < 1) || (vlanNumber > 4094)))
				throw new ArgumentOutOfRangeException ("SelectedVlanNumber must be -1 or 1..4094");

			_selectedVlan = vlanNumber;

			if (_canSelectAll == false)
			{
				if (_selectedVlan == -1)
					SelectedIndex = -1;
				else if (_selectedVlan <= NumberOfItems)
					SelectedIndex = _selectedVlan - 1;
				else
					Text = _selectedVlan.ToString ();

				OnVlanChanged (EventArgs.Empty);
			}
			else
			{
				if (_selectedVlan == -1)
					SelectedIndex = 0;
				else if (_selectedVlan <= NumberOfItems)
					SelectedIndex = _selectedVlan;
				else
					Text = _selectedVlan.ToString ();

				OnVlanChanged (EventArgs.Empty);
			}
		}

		protected override void OnSelectionChangeCommitted (EventArgs e)
		{
			base.OnSelectionChangeCommitted (e);

			int vlan;
			if (SelectedIndex == -1)
			{
				vlan = -1;
			}
			else
			{
				if (_canSelectAll == false)
				{
					vlan = SelectedIndex + 1;
				}
				else
				{
					if (SelectedIndex == 0)
						vlan = -1;
					else
						vlan = SelectedIndex;
				}
			}

			if (_selectedVlan != vlan)
			{
				_selectedVlan = vlan;
				OnVlanChanged (EventArgs.Empty);
			}
		}

		bool ValidateAndSelectVlan ()
		{
			int vlan;
			if (_canSelectAll && (Text == AllVlansText))
				vlan = -1;
			else
			{
				bool parsed = int.TryParse (Text, out vlan);
				if (!parsed || (vlan < 1) || (vlan > 4094))
				{
					MessageBox.Show (this, "VLAN number must be 1..4094");
					return false;
				}
			}

			if (_selectedVlan != vlan)
			{
				_selectedVlan = vlan;
				OnVlanChanged (EventArgs.Empty);
			}

			return true;
		}

		protected override void OnValidating (CancelEventArgs e)
		{
			base.OnValidating (e);
			if (e.Cancel)
				return;

			bool validated = ValidateAndSelectVlan ();
			if (validated == false)
				e.Cancel = true;
		}

		protected override void OnKeyPress (KeyPressEventArgs e)
		{
			base.OnKeyPress (e);

			if (e.KeyChar == '\x0d')
			{
				ValidateAndSelectVlan ();
				SelectAll ();
				e.Handled = true;
			}	
		}
	}
}
